gusucode.com > VC++ 基于IE内核功能很齐全的浏览器(支持多标签)-源码程序 > VC++ 基于IE内核功能很齐全的浏览器(支持多标签)-源码程序/code/Explorer/BBHyperLink.cpp

    //Download by http://www.NewXing.com
// BBHyperLink.cpp : implementation file
//

#include "stdafx.h"
#include "BBHyperLink.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CBBHyperLink

#define TOOLTIP_ID 1

//设置风格位操作
#define SETBITS(dw, bits)	(dw |= bits)
//去掉风格位操作
#define CLEARBITS(dw, bits)	(dw &= ~(bits))
//判断风格位操作
#define BITSET(dw, bit)		(((dw) & (bit)) != 0L)

/////////////////////////////////////////////////////////////////////////////
// CBBHyperLink

const DWORD CBBHyperLink::STYLEUNDERLINE		 = 0x00000001;		// 下划线
const DWORD CBBHyperLink::STYLEUSEHOVER		 = 0x00000002;		// 鼠标的掠过颜色风格
const DWORD CBBHyperLink::STYLEAUTOSIZE	  	 = 0x00000004;		// 自动调整大小
const DWORD CBBHyperLink::STYLEDOWNCLICK		 = 0x00000008;		// 鼠标按下代表单击风格
const DWORD CBBHyperLink::STYLEGETFOCUSONCLICK = 0x00000010;		// 单击时候得到光标
const DWORD CBBHyperLink::STYLENOHANDCURSOR	 = 0x00000020;		// 没有设置光标
const DWORD CBBHyperLink::STYLENOACTIVECOLOR	 = 0x00000040;		// 没有活动时设置颜色

//默认的颜色
COLORREF CBBHyperLink::m_crLinkColor		= RGB(0, 0, 255);	
COLORREF CBBHyperLink::m_crActiveColor	= RGB(0, 128, 128);	
COLORREF CBBHyperLink::m_crVisitedColor	= RGB(128, 0, 128);	
COLORREF CBBHyperLink::m_crHoverColor		= RGB(255, 0, 0	);	

HCURSOR	 CBBHyperLink::m_hLinkCursor		= NULL;				

CBBHyperLink::CBBHyperLink()
{
	m_bOverControl		= FALSE;	// 光标不在控件上
	m_bVisited			= FALSE;	// 可见
	m_bLinkActive		= FALSE;	// 活动
	m_strURL.Empty();				// URL
	// 设置默认的风格
	m_dwStyle = STYLEUNDERLINE|STYLEAUTOSIZE|STYLEGETFOCUSONCLICK;
}

CBBHyperLink::~CBBHyperLink()
{
    m_Font.DeleteObject();
}

IMPLEMENT_DYNAMIC(CBBHyperLink, CStatic)

BEGIN_MESSAGE_MAP(CBBHyperLink, CStatic)
    //{{AFX_MSm_MAP(CBBHyperLink)
    ON_WM_CTLCOLOR_REFLECT()
    ON_WM_SETCURSOR()
    ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_KEYDOWN()
	ON_WM_NCHITTEST()
	ON_WM_LBUTTONDOWN()	
	//}}AFX_MSm_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBBHyperLink message handlers

BOOL CBBHyperLink::PreTranslateMessage(MSG* pMsg) 
{
    m_ToolTip.RelayEvent(pMsg);
    return CStatic::PreTranslateMessage(pMsg);
}

void CBBHyperLink::PreSubclassWindow() 
{		    
	// 如果URL为空,以显示文本为连接对象
    if (m_strURL.IsEmpty())
        GetWindowText(m_strURL);

    //检查是否为空
    CString strWndText;
    GetWindowText(strWndText);
    if (strWndText.IsEmpty()) 
	{	
        //ASSERT(!m_strURL.IsEmpty());    
		CStatic::SetWindowText(m_strURL);
    }

    //得到字体
    CFont* pFont = GetFont();	
	
	if (pFont != NULL) 
	{
		LOGFONT lf;
		pFont->GetLogFont(&lf);
		lf.lfUnderline = BITSET(m_dwStyle, STYLEUNDERLINE);
		if (m_Font.CreateFontIndirect(&lf))
			CStatic::SetFont(&m_Font);    
		//调整窗口的大小,以适应字体的全部可见
		AdjustWindow();
	}
	else 
	{				
		//如果没有得到字体,说明本控件不是一个Text类型的,
		//把其设置成自动伸缩
		CLEARBITS(m_dwStyle,STYLEAUTOSIZE);
	}
	
	if (!BITSET(m_dwStyle,STYLENOHANDCURSOR))
		SetDefaultCursor();     

    //提示
    CRect rect; 
    GetClientRect(rect);
    m_ToolTip.Create(this);	
    m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);

    CStatic::PreSubclassWindow();
}

//设置字体和颜色
HBRUSH CBBHyperLink::CtlColor(CDC* pDC, UINT nCtlColor) 
{		
	ASSERT(nCtlColor == CTLCOLOR_STATIC);

	if (m_bOverControl && BITSET(m_dwStyle,STYLEUSEHOVER))
	{
		pDC->SetTextColor(m_crHoverColor);
	}
	else if (!BITSET(m_dwStyle,STYLENOACTIVECOLOR) && m_bLinkActive)
	{
		pDC->SetTextColor(m_crActiveColor);
	}
	else if (m_bVisited)
	{
		pDC->SetTextColor(m_crVisitedColor);
	}
	else
	{
		pDC->SetTextColor(m_crLinkColor);
	}
	
	pDC->SetBkMode(TRANSPARENT);
	return (HBRUSH)GetStockObject(NULL_BRUSH);
}

void CBBHyperLink::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (m_bOverControl)        // 当前在
	{
		CRect rect;
		GetClientRect(rect);

		if (!rect.PtInRect(point))
		{
			m_bOverControl = FALSE;
			ReleaseCapture();
			Invalidate();						
			return;
		}			
	}
	else                      // 光标已经离开
	{
		m_bOverControl = TRUE;
		Invalidate();		
		SetCapture();		
	}
}

//通常,如果没有SS_NOTIFY,Static控件得不到到鼠标事件,
//本函数完成了与SS_NOTIFY
//的效果,但在调用OnCtlColor时打开SS_NOTIFY更可靠,因为在Bitamap风格的Static中没有
//发送WM_CTLCOLOR的消息

UINT CBBHyperLink::OnNcHitTest(CPoint point) 
{
	return HTCLIENT;	
}

void CBBHyperLink::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if (BITSET(m_dwStyle,STYLEGETFOCUSONCLICK))
	{
		SetFocus();				
	}
	if (BITSET(m_dwStyle,STYLEDOWNCLICK))
	{
		FollowLink();
	}
	m_bLinkActive = TRUE;
}

void CBBHyperLink::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if (m_bLinkActive && !BITSET(m_dwStyle,STYLEDOWNCLICK))
		FollowLink();
}

BOOL CBBHyperLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{	
	if (m_hLinkCursor)
	{
		::SetCursor(m_hLinkCursor);
		return TRUE;
	}
	return FALSE;
}

void CBBHyperLink::OnSetFocus(CWnd* pOldWnd) 
{
	m_bLinkActive = TRUE;
	Invalidate();							// Repaint to set the focus
}

void CBBHyperLink::OnKillFocus(CWnd* pNewWnd) 
{	
	// Assume that control lost focus = mouse out
	// this avoid troubles with the Hover color
	m_bOverControl = FALSE;
	m_bLinkActive = FALSE;
	Invalidate();							// Repaint to unset the focus
}

void CBBHyperLink::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{	
	//空格
	if (nChar == VK_SPACE)
	{
		FollowLink();
	}
	else
	{
		CStatic::OnKeyDown(nChar, nRepCnt, nFlags);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CBBHyperLink operations

void CBBHyperLink::SetColors(	COLORREF crLinkColor,
							COLORREF crActiveColor,
							COLORREF crVisitedColor,
                            COLORREF crHoverColor /* = -1 */) 
{
	m_crLinkColor    = crLinkColor;
	m_crActiveColor	 = crActiveColor;
	m_crVisitedColor = crVisitedColor;	

	if (crHoverColor == -1)
		m_crHoverColor = ::GetSysColor(COLOR_HIGHLIGHT);
	else
		m_crHoverColor = crHoverColor;	
}


void CBBHyperLink::GetColors(COLORREF	&crLink,COLORREF &crActive,COLORREF	&crVisited,COLORREF	&crHover)
{	
	crLink=m_crLinkColor;
	crActive = m_crActiveColor;
	crVisited = m_crVisitedColor;
	crHover = m_crHoverColor;
}

void CBBHyperLink::SetLinkCursor(HCURSOR hCursor) {
	ASSERT(hCursor != NULL);

	m_hLinkCursor = hCursor;
	if (m_hLinkCursor == NULL)
		SetDefaultCursor();
}

HCURSOR CBBHyperLink::GetLinkCursor() {
	return m_hLinkCursor;
}

BOOL CBBHyperLink:: ModifyLinkStyle(DWORD dwRemove, DWORD dwAdd,
								  BOOL bApply /* =TRUE */)
{
	
	if ((dwRemove & dwAdd) != 0L)
		return FALSE;
	
	CLEARBITS(m_dwStyle, dwRemove);
	SETBITS(m_dwStyle, dwAdd);		
	if (bApply && ::IsWindow(GetSafeHwnd())) 	
	{
	
		if (BITSET(dwAdd,STYLEUNDERLINE) || BITSET(dwRemove,STYLEUNDERLINE))
			SwitchUnderline();		
		if (BITSET(dwAdd,STYLEAUTOSIZE))
			AdjustWindow();		
		if (BITSET(dwRemove,STYLEUSEHOVER))
			Invalidate();
	}
	return TRUE;
}

DWORD CBBHyperLink::GetLinkStyle() const {
	return m_dwStyle;
}

void CBBHyperLink::SetURL(CString strURL)
{
	m_strURL = strURL;

	if (::IsWindow(GetSafeHwnd())) 
	{
		ShowWindow(SW_HIDE);
		AdjustWindow();
		m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
		ShowWindow(SW_SHOW);
	}
}

CString CBBHyperLink::GetURL() const 
{ 
	return m_strURL;   
}

void CBBHyperLink::SetWindowText(LPCTSTR lpszText)
{
	ASSERT(lpszText != NULL);

	if (::IsWindow(GetSafeHwnd())) 
	{		
		ShowWindow(SW_HIDE);					
		CStatic::SetWindowText(lpszText);		
		AdjustWindow();
		ShowWindow(SW_SHOW);			
	}
}

void CBBHyperLink::SetFont(CFont* pFont)
{
	ASSERT(::IsWindow(GetSafeHwnd()));
	ASSERT(pFont != NULL);	
	ShowWindow(SW_HIDE);				
	LOGFONT lf;	
	pFont->GetLogFont(&lf);
	m_Font.DeleteObject();
	m_Font.CreateFontIndirect(&lf);	
	CStatic::SetFont(&m_Font);	
	AdjustWindow();
	ShowWindow(SW_SHOW);				
}


void CBBHyperLink::SwitchUnderline()
{	
	LOGFONT lf;
	CFont* pFont = GetFont();
	if (pFont != NULL) 
	{
		pFont->GetLogFont(&lf);		
		lf.lfUnderline = BITSET(m_dwStyle,STYLEUNDERLINE);
		m_Font.DeleteObject();
		m_Font.CreateFontIndirect(&lf);
		SetFont(&m_Font);					
	}	
}

//调整窗口的大小,以适应文字的大小
void CBBHyperLink::AdjustWindow()
{	
	ASSERT(::IsWindow(GetSafeHwnd()));
    
	if (!BITSET(m_dwStyle,STYLEAUTOSIZE)) 
		return;

    
    CRect rcWnd;
    GetWindowRect(rcWnd);

	//父窗口先转换
    CWnd* pParent = GetParent();
    if (pParent)
        pParent->ScreenToClient(rcWnd);
	

	CRect rcClient;
	GetClientRect(rcClient);

	// 计算边框
	int borderWidth = rcWnd.Width() - rcClient.Width();
	int borderHeight = rcWnd.Height() - rcClient.Height();

    // 得到字体的尺寸
    CString strWndText;
    GetWindowText(strWndText);	
    CDC* pDC = GetDC();	
    CFont* pOldFont = pDC->SelectObject(&m_Font);
    CSize Extent = pDC->GetTextExtent(strWndText);
    pDC->SelectObject(pOldFont);
    ReleaseDC(pDC);

    
	//得到字体的对方式
    DWORD dwStyle = GetStyle();    
    if (BITSET(dwStyle, SS_CENTERIMAGE))
	{
		rcWnd.DeflateRect(0, (rcWnd.Height() - Extent.cy) / 2);
	}
    else
	{
		rcWnd.bottom = rcWnd.top + Extent.cy;
	}

    if (BITSET(dwStyle, SS_CENTER))
	{
		rcWnd.DeflateRect((rcWnd.Width() - Extent.cx) / 2, 0);
	}
    else if (BITSET(dwStyle,SS_RIGHT))
	{
		rcWnd.left  = rcWnd.right - Extent.cx;
	}
	else // SS_LEFT
	{
		rcWnd.right = rcWnd.left + Extent.cx;
	}
	
	MoveWindow(rcWnd.left, rcWnd.top, rcWnd.Width() + borderWidth,
		rcWnd.Height() + borderHeight);
}

void CBBHyperLink::SetVisited(BOOL bVisited /* = TRUE */) {
	m_bVisited = bVisited;
}

BOOL CBBHyperLink::IsVisited() const {
	return m_bVisited;
}

/////////////////////////////////////////////////////////////////////////////
// CBBHyperLink implementation

// 从WIn32hlp中得到默认的手形光标
void CBBHyperLink::SetDefaultCursor()
{
	//如果仅在Win2000中可以用
	//HCURSOR hHandCursor=::LoadCursor(NULL,IDC_HAND);
	//m_hLinkCursor = CopyCursor(hHandCursor);
	//return;
	//否则用
	if (m_hLinkCursor == NULL)		
	{
        
		CString strWndDir;
		GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
		strWndDir.ReleaseBuffer();

		strWndDir += _T("\\winhlp32.exe");
		
		HMODULE hModule = LoadLibrary(strWndDir);
		if (hModule) 
		{
			HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
			if (hHandCursor)				
				m_hLinkCursor = CopyCursor(hHandCursor);
		}
		FreeLibrary(hModule);
	}
}

HINSTANCE CBBHyperLink::GotoURL(LPCTSTR url, int showcmd)
{
    HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);
    return result;
}

// 激活连接控件
void CBBHyperLink::FollowLink() 
{	
	int result = (int) GotoURL(m_strURL, SW_SHOW);
    if (result <= HINSTANCE_ERROR)
	{
        MessageBeep(MB_ICONEXCLAMATION);	        
    } 
	else 
	{
		m_bVisited = TRUE;
		Invalidate();
	}
}